做自己吧,因為其他人已經有人做了。 -王爾德
說到logging的重要性,我本身有很深的體悟,在前公司是負責軟體開發,公司有開發電子硬體,軟體需要串接韌體的讀寫,此時,我們在讀寫的過程中都有透過logging記錄一些行為,如果讀寫的過程有出入,方便去追蹤問題的過程,以便解析哪一端(工廠端,韌體端或是軟體端)發生問題。
後端在運行時,非常需要log紀錄操作數據的動作,每則日誌消息可以表達出程式在哪裡執行以及發生什麼事,Spring Boot使用了Apache Commons logging為內部log,默認配置有Java Util Logging,Log4J,Log4J2和Logback。
SLF4J(Simple Logging Facade For Java)一個可作為各種日誌記錄框架,定義了統一抽象介面,Logback效率更高並能運行在諸多環境,並實作了SLF4J API。
一般Log Format
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
但是在我們一開始建立專案時,spring-boot-starter
就已經有引入spring-boot-starter-logging
,Spring Boot 預設的日誌框架為Logback。
private static final Logger logger
= LoggerFactory.getLogger(Example.class);
使用logger 提供的方法
logger.info()
logger.warn()
logger.error()
logger.debug()
在HTTP request 到TodoController 之前寫的/api/todos 時,印出log
@RestController
@RequestMapping("/api")
public class TodoController {
private static final Logger logger
= LoggerFactory.getLogger(TodoController.class);
@Autowired
TodoService todoService;
@GetMapping("/todos")
public ResponseEntity getTodos() {
Iterable<Todo> todoList = todoService.getTodos();
logger.info("Hi...");
logger.error("I am an error");
logger.warn("Warning!.");
return ResponseEntity.status(HttpStatus.OK).body(todoList);
}
}
配置在src / main / resourses/ 底下放入預設會是這樣的檔名 logback.xml
<configuration>
<!-- 設置變數,將檔案位置設為./logs-->
<property name="LOG_PATH" value="./logs" />
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<!--用ThresholdFilter過濾ERROR以上級別才顯示在terminal上~-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<encoder>
<!-- 印出Log的格式 -->
<!-- %d{YYYY-MM-dd HH: mm:ss.SSS} log 時間 -->
<!-- %thread 執行緒名字 -->
<!-- %highlight 顯示高亮顏色 -->
<!-- %-5level log級別且顯示5個字,靠左對齊 -->
<!-- %logger log的名字 -->
<!-- %msg log訊息 -->
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!--输出到文件-->
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 輸出文件的位置,以每一天做切割-->
<fileNamePattern>${LOG_PATH}/logback.%d{yyyy-MM-dd}.log</fileNamePattern>
<!--保留30天的歷史紀錄 -->
<maxHistory>30</maxHistory>
</rollingPolicy>
<!--設定WARN以上級別才需要輸出至檔案-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>WARN</level>
</filter>
<encoder>
<!--Log的格式-->
<pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<!--把appender加上去-->
<appender-ref ref="console" />
<appender-ref ref="file" />
</root>
</configuration>
由於我們設置印出log時terminal只需要顯示Error以上的級別,所以依照上述範例,在ToDoController HTTP
Log file輸出在logs/logback.2020-10-04.log,設置顯示log時,WARN以上級別才需要輸出至檔案,顯示如下: